Repository navigation
fix(mcp): describe_object skips the hidden search companion on both transports - #33558
objectstack-fleet[bot] wants to merge 10 commits into
Conversation
…f scope Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016WV4cw787kMeaX7oyz7DDC
Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016WV4cw787kMeaX7oyz7DDC
Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016WV4cw787kMeaX7oyz7DDC
Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016WV4cw787kMeaX7oyz7DDC
…objectql entry The first validate_expression call imported the @objectstack/objectql barrel, whose metadata-protocol graph a standalone process has not loaded; under the source alias that first call outran a 5 s test budget. Load SEARCH_COMPANION_FIELD from @objectstack/objectql/core (ADR-0076) instead. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016WV4cw787kMeaX7oyz7DDC
… not the engine The first validate_expression call imported the engine to read one constant; under the test source alias that first call outran a 5 s budget, and in a standalone process it loads the engine for a string. The name now lives in @objectstack/spec/data as SEARCH_COMPANION_FIELD; objectql provisions under it and re-exports it unchanged, and mcp imports it statically from the spec, so mcp keeps objectql as a test-only dependency. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016WV4cw787kMeaX7oyz7DDC
Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016WV4cw787kMeaX7oyz7DDC
…ange) Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016WV4cw787kMeaX7oyz7DDC
…ransports The registry serves an object with the hidden __search companion beside its display field where pinyin search is on. describe_object listed it, while no caller may read, write or name it. Both describeServedObject twins now skip SEARCH_COMPANION_FIELD (from @objectstack/spec/data), pinned on the stdio tool and resource and on the HTTP bridge over a real engine. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016WV4cw787kMeaX7oyz7DDC
📓 Docs Drift Check3 anchor(s) derived from 4 changed package(s); no hand-written page names any of them. What this run could not see
Coarse fallback — 182 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): Which tree this was computed onThis run read A worktree cut from an older # while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 48c60583ffa1b2a8484d5384f008ec7dd8e597cd && git checkout 48c60583ffa1b2a8484d5384f008ec7dd8e597cd
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 8e63ed877771d6f3492309e596fb5422b3f0898e 59ae25a92d9954d0ec48801dda51648ea764667e && git checkout -B drift-repro 8e63ed877771d6f3492309e596fb5422b3f0898e && git merge --no-ff 59ae25a92d9954d0ec48801dda51648ea764667e
node scripts/docs-audit/affected-docs.mjs --json 8e63ed877771d6f3492309e596fb5422b3f0898e |
|
Contract-review-claim: session_016WV4cxDxAYxdtDhtR1kQQe · head 59ae25a · 2026-11-15T00:49:45Z |
Review: PASSreview#2 (server area pilot) · area A4 · Fixes #33454 (p1) · head Stacked on #33451. This PR's own change is the single commit What was checked:
Semver: Not run locally (declared): 7 gate families were skipped. Full CI on this head stands in for them; the merge waits for it as usual. Nits: none. Final round. If the verdict lands after A4's handover, the next A4 session lands it after merging Generated by Claude Code |
Requested by Elon · project thread
Fixes #33454
Clause-②: no
Metadata-protocol: none
维护者速读
describe_object在两个传输(HTTP 桥packages/runtime/src/domains/mcp.ts、stdio 桥与objectstack://objects/{name}资源packages/mcp/src/mcp-server-runtime.ts)都不再列出隐藏的__search搜索伴随列。__search列,但任何调用方都不能读、写或点名它;describe_object却把它当字段提供给 agent,与其它入口(记录读取、$searchFields、validate_expression)全都拒收相矛盾。describeServedObject加一个按名过滤,常量来自@objectstack/spec/data,无新依赖、不加载引擎;回滚即还原该提交。packages/runtime/src/domains/mcp.ts(HTTP 孪生的过滤行)、packages/mcp/src/mcp-server-runtime.ts(stdio 孪生的过滤行)、packages/runtime/src/domains/mcp-object-schema-mask.test.ts(真实引擎上的钉子)。pnpm --filter @objectstack/runtime exec vitest run src/domains/mcp-object-schema-mask.test.ts -t 'hidden search companion',预期 2 passed。What changes
describeServedObjectinpackages/mcp/src/mcp-server-runtime.ts(the stdio bridge'sdescribe_objectand theobjectstack://objects/{name}resource) and its HTTP twin inpackages/runtime/src/domains/mcp.tsnow skip the field namedSEARCH_COMPANION_FIELD.@objectstack/spec/data, the import fix(mcp): validate_expression keeps the hidden __search companion out of scope #33451 uses inmcp-http-tools.ts. Neither file gains an engine import.@objectstack/spec, which is outside this card's file surface. Each twin skips the field by the one protocol constant, so no second list exists.organization_id,created_at,updated_at).patchfor@objectstack/mcpand@objectstack/runtime.Tests
Two pins, each added as a top-level
describein the transport's existing describe_object harness:packages/runtime/src/domains/mcp-object-schema-mask.test.ts. Uses a realObjectQLover a realSqlDriver, withOS_SEARCH_PINYIN_ENABLED=true(the switch the registry reads when it is built) and the protocol over that engine, driven through the real/mcpdispatcher entry.servedObjectDefinitionOfboth carry__search.describeObjectanswer has no__searchanywhere in its text, and still listsname,email,created_at,updated_atandorganization_id.packages/mcp/src/stdio-data-bridge.object-schema-mask.test.ts. The served object is built with the producer's ownprovisionSearchCompanion(applyInjectedSystemColumns(...)), not a transcription of its output.describe_objecttool, called through a real MCP client, and over theobjectstack://objects/{name}resource.Measured before the fix (premise re-check): the HTTP pin failed with
expected [ 'organization_id', …(10) ] to not include '__search', and both stdio cases failed the same way.Ablation (fix committed first, mutation through scripts/ablation-replace.mjs)
The first attempt passed an empty
--replacement, which the tool refused because a zero-length replacement cannot be counted. No test ran on that attempt and its reading is void. It was re-run with--delete:Both suites import the edited module from source (relative imports), so no
dist/sits between the mutation and the test.Runs at 59ae25a
pnpm --filter @objectstack/mcp exec vitest run --maxWorkers=2: Test Files 64 passed (64), Tests 1180 passed (1180)pnpm --filter @objectstack/runtime exec vitest run --maxWorkers=2 --project local src/domains: Test Files 215 passed (215), Tests 5029 passed (5029)pnpm --filter @objectstack/mcp run typecheck: exit 0.check:test-typecheckOK.pnpm --filter @objectstack/runtime run typecheck: exit 0. The first run went red on two untouched test files (Cannot find module '@objectstack/driver-turso') because that package was not yet built in this fresh worktree. After building it:check:test-typecheck: OK.eslint --no-inline-configon the four touched source and test files: exit 0.Acceptance notes
validate_expression(mcp-http-tools.ts, from fix(mcp): validate_expression keeps the hidden __search companion out of scope #33451) is redundant whenever the bridge'sdescribeObjectis one of the two twins. It is left in place as that tool's own statement of its scope.servedObjectDefinitionOfstill returns the served definition whole, companion included. That is the definitionvalidate_expressionhands the publish gate's passes, and this card does not change it.Verification
Gate families derived by
node scripts/pm/dispatch-gates.mjs --commandsat 59ae25a, then reconciled with--ran. The change set includes #33451's commits because the branch is stacked on it. The per-family verdicts are in the os-dev report comment on #33454.🤖 Generated with Claude Code
https://claude.ai/code/session_016WV4cw787kMeaX7oyz7DDC